﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Diagnostics.CodeAnalysis;

namespace Leo.Common.Json
{
    public class JSON
    { 
        private static readonly JsonSerializerSettings _settings = new JsonSerializerSettings();
        private static bool IsExist(IList<JsonConverter> list, JsonConverter converter)
        {
            if (list == null || list.Count <= 0 || converter == null)
            {
                return false;
            }
            Type converterType = converter.GetType();
            return Enumerable.Any<JsonConverter>(list, (JsonConverter t) => t.GetType() == converterType);
        }

        public static IsoDateTimeConverter GetJsonDateFormat()
        {
            return new IsoDateTimeConverter
            {
                DateTimeFormat = "yyyy-MM-dd HH:mm:ss"
            };
        }

        public static T Deserialize<T>(string json)
        {
            return JsonConvert.DeserializeObject<T>(json, JSON._settings);
        }

        public static T Deserialize<T>(string json, JsonSerializerSettings setting)
        {
            return JsonConvert.DeserializeObject<T>(json, setting);
        }

        public static object Deserialize(string json, Type targetType, Action<JsonSerializerSettings> configure)
        {
            JsonSerializerSettings jsonSerializerSettings = JSON.Clone(configure);
            return JsonConvert.DeserializeObject(json, targetType, jsonSerializerSettings);
        }

        public static T Deserialize<T>(string json, Action<JsonSerializerSettings> configure)
        {
            JsonSerializerSettings jsonSerializerSettings = JSON.Clone(configure);
            return JsonConvert.DeserializeObject<T>(json, jsonSerializerSettings);
        }

        static JSON()
        {
            JsonSerializerSettings settings = JSON._settings;
            if (settings.Converters == null)
            {
                settings.Converters = new List<JsonConverter>();
            }
            JSON._settings.Converters.Add(JSON.GetJsonDateFormat());
        }

        public static void Configure(Action<JsonSerializerSettings> action)
        {
            if (action != null)
            {
                action.Invoke(JSON._settings);
            }
        }

        private static JsonSerializerSettings Clone(Action<JsonSerializerSettings> configure)
        {
            if (configure == null)
            {
                return JSON._settings;
            }
            JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
            {
                SerializationBinder = JSON._settings.SerializationBinder,
                StringEscapeHandling = JSON._settings.StringEscapeHandling,
                DateFormatString = JSON._settings.DateFormatString,
                DateFormatHandling = JSON._settings.DateFormatHandling,
                DateParseHandling = JSON._settings.DateParseHandling,
                DateTimeZoneHandling = JSON._settings.DateTimeZoneHandling,
                DefaultValueHandling = JSON._settings.DefaultValueHandling,
                MaxDepth = JSON._settings.MaxDepth,
                CheckAdditionalContent = JSON._settings.CheckAdditionalContent,
                ConstructorHandling = JSON._settings.ConstructorHandling,
                Context = JSON._settings.Context,
                ContractResolver = JSON._settings.ContractResolver,
                Converters = JSON._settings.Converters,
                Culture = JSON._settings.Culture,
                EqualityComparer = JSON._settings.EqualityComparer,
                ObjectCreationHandling = JSON._settings.ObjectCreationHandling,
                Error = JSON._settings.Error,
                FloatFormatHandling = JSON._settings.FloatFormatHandling,
                FloatParseHandling = JSON._settings.FloatParseHandling,
                Formatting = JSON._settings.Formatting,
                TraceWriter = JSON._settings.TraceWriter,
                TypeNameAssemblyFormatHandling = JSON._settings.TypeNameAssemblyFormatHandling,
                TypeNameHandling = JSON._settings.TypeNameHandling,
                MetadataPropertyHandling = JSON._settings.MetadataPropertyHandling,
                MissingMemberHandling = JSON._settings.MissingMemberHandling,
                NullValueHandling = JSON._settings.NullValueHandling,
                PreserveReferencesHandling = JSON._settings.PreserveReferencesHandling,
                ReferenceLoopHandling = JSON._settings.ReferenceLoopHandling,
                ReferenceResolverProvider = JSON._settings.ReferenceResolverProvider
            };
            configure.Invoke(jsonSerializerSettings);
            return jsonSerializerSettings;
        }

        public static string Serialize(object arg)
        {
            return JsonConvert.SerializeObject(arg, JSON._settings);
        }

        public static string Serialize(object arg, Action<JsonSerializerSettings> configure)
        {
            JsonSerializerSettings jsonSerializerSettings = JSON.Clone(configure);
            return JsonConvert.SerializeObject(arg, jsonSerializerSettings);
        }
         
        public static string Serialize(object arg, JsonSerializerSettings settings)
        {
            return JsonConvert.SerializeObject(arg, settings);
        }
       
    }
}
